package com.easylinkin.linkappapi.jglplant.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.additional.query.impl.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.common.exceptions.BusinessException;
import com.easylinkin.linkappapi.common.service.CommonService;
import com.easylinkin.linkappapi.common.utils.excel.ExcelConstant;
import com.easylinkin.linkappapi.common.utils.excel.ExcelTools;
import com.easylinkin.linkappapi.common.utils.io.OutputStreamUtil;
import com.easylinkin.linkappapi.jglplant.dao.JglExpertDao;
import com.easylinkin.linkappapi.jglplant.dao.JglPlantRefExpertDao;
import com.easylinkin.linkappapi.jglplant.entity.JglExpert;
import com.easylinkin.linkappapi.jglplant.entity.JglExpertResearchArea;
import com.easylinkin.linkappapi.jglplant.entity.JglExpertVo;
import com.easylinkin.linkappapi.jglplant.entity.JglPlantRefExpert;
import com.easylinkin.linkappapi.jglplant.service.JglExpertResearchAreaService;
import com.easylinkin.linkappapi.jglplant.service.JglExpertService;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 鸡公岭-专家库(JglExpert)表服务实现类
 *
 * @author makejava
 * @since 2022-02-22 10:34:34
 */
@Slf4j
@Service("jglExpertService")
public class JglExpertServiceImpl extends ServiceImpl<JglExpertDao, JglExpert> implements JglExpertService {
    @Resource
    private CommonService commonService;
    @Resource
    private LinkappUserContextProducer linkappUserContextProducer;
    @Resource
    private JglExpertResearchAreaService jglExpertResearchAreaService;
    @Resource
    private JglPlantRefExpertDao jglPlantRefExpertDao;

    @Override
    public boolean saveOne(JglExpert jglExpert) {
        commonService.setCreateAndModifyInfo(jglExpert);
        jglExpert.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        validParamRequired(jglExpert);
        validRepeat(jglExpert);
        validParamFormat(jglExpert);
        boolean r = save(jglExpert);
        saveExpertResearchAreaList(jglExpert);
        return r;
    }

    private void saveExpertResearchAreaList(JglExpert jglExpert) {
        Set<String> typeSet = new LinkedHashSet<>();
        List<JglExpertResearchArea> jglExpertResearchAreaList = jglExpert.getJglExpertResearchAreaList();
        if (jglExpertResearchAreaList != null) {
            Assert.isTrue(jglExpertResearchAreaList.size() <= 3, "专家研究领域需不大于3个");
            for (JglExpertResearchArea jglExpertResearchArea : jglExpertResearchAreaList) {
//                    不同时为空
                if (jglExpertResearchArea != null && jglExpertResearchArea.notAllTypeEmpty()) {
                    jglExpertResearchArea.setExpertId(jglExpert.getId());
                    if (!typeSet.contains(jglExpertResearchArea.allTypeToString())) {
                        jglExpertResearchAreaService.save(jglExpertResearchArea);
                    }
                    typeSet.add(jglExpertResearchArea.allTypeToString());
                }
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateOne(JglExpert jglExpert) {
        Assert.notNull(jglExpert.getId(), "id不能为空");
        commonService.setModifyInfo(jglExpert);
        jglExpert.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        validRepeat(jglExpert);
        validParamFormat(jglExpert);
        boolean r = updateById(jglExpert);
        QueryWrapper<JglExpertResearchArea> qw = new QueryWrapper<>();
        qw.eq("expert_id", jglExpert.getId());
        jglExpertResearchAreaService.remove(qw);
        saveExpertResearchAreaList(jglExpert);
        return r;
    }

    @Override
    public IPage<JglExpert> selectPage(Page page, JglExpert jglExpert) {
        jglExpert.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        long start = (page.getCurrent() - 1) * page.getSize();
        start = start < 0 ? 0 : start;
        List<JglExpert> records =baseMapper.getPageList(start, page.getSize(), jglExpert);
        IPage<JglExpert> r = new Page<>();
        r.setRecords(records);
        r.setCurrent(page.getCurrent());
        r.setSize(r.getRecords().size());
        r.setTotal(baseMapper.getPageCount(jglExpert));
//        手动排序 研究领域
        for (JglExpert record : r.getRecords()) {
            List<JglExpertResearchArea> jglExpertResearchAreaList = record.getJglExpertResearchAreaList();
            if (CollectionUtils.isEmpty(jglExpertResearchAreaList)) {
                List<JglExpertResearchArea> jglExpertResearchAreaList1 = jglExpertResearchAreaList.stream().sorted((Comparator.comparing(o -> ("" + o.getType1() + o.getType2() + o.getType3() + o.getType4())))).collect(Collectors.toList());
                record.setJglExpertResearchAreaList(jglExpertResearchAreaList1);
            }
        }
        return r;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteByIds(List<Long> idList) {
        int count = new LambdaQueryChainWrapper<>(jglPlantRefExpertDao)
                .in(JglPlantRefExpert::getExpertId, idList)
                .count();
        Assert.isTrue(count == 0, "该专家被植物引用，不允许删除");
//        删除专家关联的研究领域
        QueryWrapper<JglExpertResearchArea> qw = new QueryWrapper<>();
        qw.in("expert_id", idList);
        jglExpertResearchAreaService.remove(qw);
        return removeByIds(idList);
    }

    @Override
    public void export(JglExpert jglExpert, HttpServletRequest request, HttpServletResponse response) {

        IPage<JglExpert> page = selectPage(new Page(0, -1), jglExpert);
        List<JglExpert> records = page.getRecords();
        List<JglExpertVo> jglExpertVos = new ArrayList<>();
        for (JglExpert expert : records) {
            jglExpertVos.add(new JglExpertVo(expert));
        }

        String keyValue = "名称:name,性别:genderStr,单位:company," +
                "职称:job,研究领域1:study1,研究领域2:study2,研究领域3:study3,研究植物:studyPlant,备注:remark";
        String title = "专家列表导出数据";
        String fileName = title + ".xls";
        try {
            OutputStream outputStream = OutputStreamUtil
                    .getOutputStream(request, response, fileName);
            ExcelTools.exportExcel(outputStream, keyValue, jglExpertVos, ExcelConstant.XLS, title);
            response.flushBuffer();
            outputStream.close();
        } catch (IOException e) {
            log.error("excel导出失败", e);
            throw new RuntimeException("excel导出失败！IOException异常" + e.getMessage());
        } catch (Exception e) {
            log.error("excel导出失败", e);
            throw new RuntimeException("excel导出失败！" + e.getMessage());
        }
    }

    @Override
    public JglExpert getOneById(Serializable id) {
        return baseMapper.getOneById(id);
    }

    /**
     * 校验重复
     */
    private void validRepeat(JglExpert jglExpert) {
        QueryWrapper<JglExpert> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", jglExpert.getName());
        if (jglExpert.getCompany() != null) {
            queryWrapper.eq("company", jglExpert.getCompany());
        }
        if (jglExpert.getGender() != null) {
            queryWrapper.eq("gender", jglExpert.getGender());
        }
        queryWrapper.eq("tenant_id", linkappUserContextProducer.getNotNullCurrent().getTenantId());
        List<JglExpert> list = baseMapper.selectList(queryWrapper);
        if (list.size() == 0) {
            return;
        }
        if (list.size() > 1) {
            throw new BusinessException("专家名称有重复");
        }
        if (ObjectUtils.isEmpty(jglExpert.getId())) {
            throw new BusinessException("专家名称已存在");
        }
        if (!jglExpert.getId().equals(list.get(0).getId())) {
            throw new BusinessException("专家名称已存在");
        }

    }


    /**
     * 校验参数必填
     */
    private void validParamRequired(JglExpert jglExpert) {
        Assert.notNull(jglExpert, "参数为空");
        Assert.isTrue(StringUtils.isNotBlank(jglExpert.getName()), "名称为空");
        Assert.isTrue(ObjectUtils.isNotEmpty(jglExpert.getGender()), "性别为空");
        Assert.isTrue(ObjectUtils.isNotEmpty(jglExpert.getCompany()), "单位为空");
        Assert.isTrue(StringUtils.isNotBlank(jglExpert.getTenantId()), "租户id为空");
    }

    /**
     * 校验参数格式
     */
    private void validParamFormat(JglExpert jglExpert) {
        Assert.isTrue(jglExpert.getName() == null || jglExpert.getName().length() <= 50, "专家名称超长");
        Assert.isTrue(jglExpert.getCompany() == null || jglExpert.getCompany().length() <= 50, "单位名称超长");
    }
}

